#pragma once

#include <httplib.h>
#include <spdlog/spdlog.h>
#include "../util/server.hh"
#include "../util/response.hh"
#include "../poco/user.hh"
#include "../service/user-service.hh"

namespace WordMemory
{
    class UserController
    {
    public:
        static void registerBusiness()
        {
            Server::instance().regist<Server::BusType::POST>("/api/user/login", loginUser);
            Server::instance().regist<Server::BusType::POST>("/api/user/register", registerUser);
            Server::instance().regist<Server::BusType::GET>("/api/user", getUser);
            Server::instance().regist<Server::BusType::PUT>("/api/user", updateUser);

            spdlog::info("User controller registered");
        }

    private:
        // 登录
        static void loginUser(const httplib::Request &req, httplib::Response &res)
        {
            Json::Value root = JsonUtil::deserialize(req.body);

            auto username = root["username"].asString();
            auto password = root["password"].asString();

            try
            {
                User user = UserService::instance().loginUser(username, password);

                res.status = 200;
                res.set_content(ResponseMessage::success(user.to_json()), "application/json");

                spdlog::info("User login success");
            }
            catch (const ServerExcept &e)
            {
                res.status = 401;
                res.set_content(ResponseMessage::error(e.what()), "application/json");

                spdlog::error("User login failed: {}", e.what());
            }
        }

        // 注册
        static void registerUser(const httplib::Request &req, httplib::Response &res)
        {
            Json::Value root = JsonUtil::deserialize(req.body);

            auto username = root["username"].asString();
            auto password = root["password"].asString();
            auto real_name = root["real_name"].asString();

            try
            {
                User user = UserService::instance().registerUser(username, password, real_name);

                res.status = 201;
                res.set_content(ResponseMessage::success(user.to_json()), "application/json");

                spdlog::info("User {} registered successfully", user.to_json().toStyledString());
            }
            catch (const ServerExcept &e)
            {
                res.status = 400;
                res.set_content(ResponseMessage::error(e.what()), "application/json");

                spdlog::error("User registration failed: {}", e.what());
            }
        }

        // 获取用户信息
        static void getUser(const httplib::Request &req, httplib::Response &res)
        {
            auto user_id = req.get_param_value("id");

            try
            {
                User user = UserService::instance().getUser(std::stoi(user_id));

                res.status = 200;
                res.set_content(ResponseMessage::success(user.to_json()), "application/json");

                spdlog::info("Fetched user info for id {}", user_id);
            }
            catch (const ServerExcept &e)
            {
                res.status = 404;
                res.set_content(ResponseMessage::error("User not found"), "application/json");

                spdlog::error("Failed to fetch user: {}", e.what());
            }
        }

        // 更新用户信息
        static void updateUser(const httplib::Request &req, httplib::Response &res)
        {
            Json::Value root = JsonUtil::deserialize(req.body);

            auto user_id = root["id"].asInt();
            auto real_name = root["real_name"].asString();

            try
            {
                User user = UserService::instance().updateUser(user_id, real_name);

                res.status = 200;
                res.set_content(ResponseMessage::success(user.to_json()), "application/json");

                spdlog::info("Updated user id {}", user_id);
            }
            catch (const ServerExcept &e)
            {
                res.status = 400;
                res.set_content(ResponseMessage::error(e.what()), "application/json");

                spdlog::error("Failed to update user: {}", e.what());
            }
        }
    };
}